﻿using Chloe.SqlServer;
using Infrastructure.Access;
using Infrastructure.Extend;
using Infrastructure.Operator;
using Infrastructure.SorketOperate;
using Infrastructure.Web;
using MyData;
using MyData.Data.Repository;
using MyData.DB;
using MyData.Dto;
using MyData.Models;
using MyDomain;
using MyRepository;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace MyRepository
{
    public class AccessRecordRepository : RepositoryBase<AccessRecord>, IAccessRecordRepository
    {
        /// <summary>
        /// 图形展示
        /// </summary>
        /// <param name="StartDate"></param>
        /// <param name="EndDate"></param>
        /// <returns></returns>
        public List<RecordChartDto> GetRecordChartDtos(DateTime StartDate, DateTime EndDate)
        {
            using (var db = this.NewDB())
            {
                var records = db.Query<AccessRecord>().Where(c => c.CreatedTime >= StartDate && c.CreatedTime <= EndDate).ToList();
                var mobiles = db.Query<Mobile>().ToList();
                var linq = (from r in records
                            group r by new { r.MobileId, r.CreateDate } into g
                            select new RecordChartDto
                            {
                                Count = g.Count(),
                                MobileId = g.Key.MobileId,
                                CreateDate = g.Key.CreateDate
                            }).ToList();

                return linq;
            }
        }
        /// <summary>
        /// 考勤记录
        /// </summary>
        /// <param name="query"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        public PageDto<CheckInDto> GetCheckIn(QueryListModel query, DateTime startDate, DateTime endDate)
        {
            using (var db = this.NewDB())
            {
                var dates = new List<string>();
                var holidays = db.Query<Holiday>().Where(c => c.StartDate > startDate || c.EndDate < endDate).ToList();
                int days = (endDate - startDate).Days + 1;
                for (int i = 0; i < days; i++)
                {
                    DateTime date = startDate.AddDays(i);
                    if (holidays.FirstOrDefault(c => c.StartDate <= date && c.EndDate >= date) != null)
                    {
                        continue;
                    }
                    dates.Add(date.ToString("yyyy-MM-dd"));
                }

                var users = db.Query<UserInfo>().OrderBy(c => c.DepartId).ToList();
                var records = db.Query<AccessRecord>().Where(c => dates.Contains(c.CreateDate)).ToList();
                var systemConfig = db.QueryByKey<SystemConfig>(Guid.Empty);
                var departs = db.Query<Depart>().ToList();
                List<CheckInDto> list = new List<CheckInDto>();
                foreach (var item in users)
                {
                    CheckInDto checkInDto = new CheckInDto();
                    checkInDto.月份 = dates[0].Substring(0, 7);
                    checkInDto.姓名 = item.NickName;
                    checkInDto.工号 = item.WorkNum;
                    checkInDto.应出勤 = dates.Count.ToString();
                    var depart = departs.FirstOrDefault(c => c.Id == item.DepartId);
                    if (depart == null)
                        continue;
                    checkInDto.部门 = depart.Name;
                    var dayrecords = records.Where(c => c.UserId == item.Id).Select(c => c.CreateDate).Distinct();
                    checkInDto.实际出勤 = dayrecords.Count().ToString();
                    int zao = 0;
                    int wan = 0;
                    int zheng = dayrecords.Count();
                    foreach (var record in dayrecords)
                    {
                        bool temp = false;
                        var zaoRecord = records.Where(c => c.CreateDate == record && c.UserId == item.Id).Min(c => c.CreatedTime);
                        if (zaoRecord > DateTime.Parse(record + " " + systemConfig.StartTime) && zaoRecord < DateTime.Parse(record + " 12:00"))
                        {
                            temp = true;
                            zao++;
                        }

                        var wanRecord = records.Where(c => c.CreateDate == record && c.UserId == item.Id).Max(c => c.CreatedTime);
                        if (wanRecord < DateTime.Parse(record + " " + systemConfig.EndTime))
                        {
                            temp = true;
                            wan++;
                        }
                        if (temp)
                        {
                            zheng--;
                        }

                    }
                    checkInDto.迟到 = zao.ToString();
                    checkInDto.早退 = wan.ToString();
                    checkInDto.缺勤 = (dates.Count - dayrecords.Count()).ToString();
                    checkInDto.正常出勤 = zheng.ToString();
                    list.Add(checkInDto);
                }
                WebHelper.WriteSession("Data", list);
                var result = list.AsQueryable().Paging(query.Limit, query.Offset);
                return new PageDto<CheckInDto>()
                {
                    total = result.total,
                    rows = result.rows
                };
            }
        }

        /// <summary>
        /// 最新记录
        /// </summary>
        /// <returns></returns>
        public RecentRecordDto GetRecentRecord()
        {
            using (var db = new RepositoryBase().BeginTrans())
            {
                var record = db.IQueryable<AccessRecord>().OrderByDescending(c => c.CreatedTime).FirstOrDefault();
                if (record == null)
                {
                    return new RecentRecordDto();
                }
                else
                {
                    var user = db.FindEntity<UserInfo>(record.UserId);
                    return new RecentRecordDto()
                    {
                        RecordId = record.Id,
                        Name = user.NickName,
                        HeadUrl = user.HeadUrl
                    };
                }
            }
        }
        /// <summary>
        /// 最新八条记录
        /// </summary>
        /// <param name="mobileId"></param>
        /// <returns></returns>
        public List<RecentRecordDto> GetRecentRecord8(Guid mobileId)
        {
            using (var db = this.NewDB())
            {
                // var records = db.Query<AccessRecord>().Where(c => c.CreatedTime > DateTime.Now.Date).OrderByDesc(c => c.CreatedTime).ToList().GroupBy(c => c.UserId).Select(c => c.FirstOrDefault());   
                var records = db.Query<AccessRecord>().Where(c => c.MobileId == mobileId).OrderByDesc(c => c.CreatedTime).ToList().GroupBy(c => c.UserId).Select(c => c.FirstOrDefault());
                var users = db.Query<UserInfo>().ToList();
                var departs = db.Query<Depart>().ToList();
                List<RecentRecordDto> results = new List<RecentRecordDto>();
                results = (from u in users
                           join d in departs on u.DepartId equals d.Id
                           join r in records on u.Id equals r.UserId
                           select new RecentRecordDto
                           {
                               DepartName = d.Name,
                               Name = u.NickName,
                               RecordTime = r.CreatedTime
                           }).Take(8).ToList();
                return results;
            }

        }
        public bool SaveRecordPic(Guid recordId, string picPath)
        {
            using (var db = new RepositoryBase().BeginTrans())
            {
                var record = db.FindEntity<AccessRecord>(recordId);
                record.PicPath = picPath;
                db.Update<AccessRecord>(record);
                return db.Commit() > 0;
            }
        }
        public List<UserRecordPicDto> GetRecordTop20()
        {
            List<UserRecordPicDto> list = new List<UserRecordPicDto>();
            using (var db = new RepositoryBase().BeginTrans())
            {
                var record = db.IQueryable<AccessRecord>().Where(c => !string.IsNullOrEmpty(c.PicPath)).OrderByDescending(c => c.CreatedTime).Take(20);
                var users = db.IQueryable<UserInfo>();
                list = (from r in record
                        join
       u in users on r.UserId equals u.Id
                        select new UserRecordPicDto()
                        {
                            NickName = u.NickName,
                            PicPath = r.PicPath,
                            RecordTime = r.CreatedTime
                        }).ToList();

                return list;

            }
        }


        public PageDto<CheckRecordDto> GetNewAccessRecord(QueryListModel query, string NickName, DateTime startDate, DateTime endDate)
        {
            using (var db = new RepositoryBase().BeginTrans())
            {
                var userList = db.IQueryable<UserInfo>().ToList();
                if (!string.IsNullOrEmpty(NickName))
                {
                    userList = userList.Where(c => c.NickName.Contains(NickName)).ToList();
                }
                var dates = new List<string>();
                var holidays = db.IQueryable<Holiday>().Where(c => c.StartDate > startDate || c.EndDate < endDate);
                int days = (endDate - startDate).Days + 1;
                var mobileList = db.IQueryable<Holiday>().ToList();
                var departList = db.IQueryable<Depart>().ToList();
                var expression = ExtLinq.True<AccessRecord>();
                expression = expression.And(c => c.CreatedTime >= startDate);
                DateTime endDateTemp = endDate.AddDays(1);
                expression = expression.And(c => c.CreatedTime <= endDateTemp);


                List<CheckRecordDto> list = new List<CheckRecordDto>();
                Stopwatch sw = Stopwatch.StartNew();
                var accessRecordList1 = db.IQueryable<AccessRecord>(expression).OrderBy(c => c.CreatedTime).ToList();

                var records = (from c in accessRecordList1
                               group c by new { c.UserId, c.CreateDate } into g
                               select new
                               {
                                   MaxTime = g.Max(x => x.CreatedTime),
                                   MinTime = g.Min(x => x.CreatedTime),
                                   UserId = g.Key.UserId,
                                   CreateDate = g.Key.CreateDate
                               }).ToList();
                for (int i = 0; i < days; i++)
                {
                    DateTime date = startDate.AddDays(i);
                    if (holidays.Count() > 0)
                    {
                        if (holidays.FirstOrDefault(c => c.StartDate <= date && c.EndDate >= date) != null)
                        {
                            continue;
                        }
                    }
                    dates.Add(date.ToString("yyyy-MM-dd"));

                }

                list = (from d in dates
                        from u in userList
                        join de in departList on u.DepartId equals de.Id
                        select new CheckRecordDto()
                        {
                            NickName = u.NickName,
                            RoleName = u.RoleName,
                            CreateDate = d,
                            DepartName = de.Name,
                            UserId = u.Id
                        }).ToList();
                foreach (var item in list)
                {
                    var record = records.FirstOrDefault(c => c.CreateDate == item.CreateDate && c.UserId == item.UserId);
                    if (record != null)
                    {
                        item.WorkOnTime = record.MinTime.ToString("yyyy-MM-dd HH:mm:ss");
                        item.WorkDownTime = record.MaxTime.ToString("yyyy-MM-dd HH:mm:ss");
                    }
                }

                //for (int i = 0; i < days; i++)
                //{
                //    foreach (var user in userList)
                //    {
                //        DateTime date = startDate.AddDays(i);
                //        if (holidays.Count() > 0)
                //        {
                //            if (holidays.FirstOrDefault(c => c.StartDate <= date && c.EndDate >= date) != null)
                //            {
                //                continue;
                //            }
                //        }
                //        CheckRecordDto dto = new CheckRecordDto();
                //        dto.NickName = user.NickName;
                //        dto.RoleName = user.RoleName;
                //        dto.CreateDate = date.ToString("yyyy-MM-dd");
                //        dto.DepartName = departList.FirstOrDefault(c => c.Id == user.DepartId)?.Name;

                //        var firstRecord = accessRecordList1.FirstOrDefault(c => c.CreateDate == dto.CreateDate && c.UserId == user.Id);
                //        var record = records.FirstOrDefault(c => c.CreateDate == dto.CreateDate && c.UserId == user.Id);
                //        if (record != null)
                //        {
                //            dto.WorkOnTime = record.MinTime.ToString("yyyy-MM-dd HH:mm:ss");
                //            dto.WorkDownTime = record.MaxTime.ToString("yyyy-MM-dd HH:mm:ss");
                //        }
                //        list.Add(dto);
                //    }
                //}
                //sw.Stop();
                //long time = sw.ElapsedMilliseconds;
                WebHelper.WriteSession("Data", list);
                var result = list.AsQueryable().Paging(query.Limit, query.Offset);
                return new PageDto<CheckRecordDto>()
                {
                    total = result.total,
                    rows = result.rows
                };
            }
        }

        /// <summary>
        /// 添加出入记录
        /// </summary>
        /// <param name="accessRecord"></param>
        /// <returns></returns>
        public bool SaveAccessRecord(AccessRecord accessRecord)
        {
            using (var db = this.NewDB())
            {
                if (PublicInfo.Version == (int)EnumVersion.行政中心)
                {
                    var user = db.QueryByKey<UserInfo>(accessRecord.UserId);
                    if (user != null)
                    {

                        string sql2 = string.Format("0;INSERT INTO CHECKINOUT([USERID],[CHECKTIME],[VERIFYCODE],[SENSORID],[sn]) VALUES({0},Now(),1,{1},{2})", user.PhoneNum, AccessConn.SENSORIDString, AccessConn.SNString);
                        string recvStr = SorketClient.SendSql(sql2);
                    }
                }
                else if (PublicInfo.Version == (int)EnumVersion.太白 && accessRecord.UserType == (int)EnumUserType.员工)
                {
                    var user = db.QueryByKey<UserInfo>(accessRecord.UserId);
                    if (user != null)
                    {
                        if (user.IsZhengShi == 2)
                        {
                            using (var db1 = new MsSqlContext(DbHelper.LinshiDBString))
                            {
                                db1.Insert<HR_ATS_OriginalityCard>(new HR_ATS_OriginalityCard()
                                {
                                    FCardDateTime = DateTime.Now,
                                    FCardID = user.WorkNum,
                                    FEmpID = user.Id,
                                    FStatus = 1
                                });
                            }
                        }
                        else if (user.IsZhengShi == 1)
                        {
                            using (var db1 = new MsSqlContext(DbHelper.ZhengshiDBString))
                            {
                                db1.Insert<HR_ATS_OriginalityCard>(new HR_ATS_OriginalityCard()
                                {
                                    FCardDateTime = DateTime.Now,
                                    FCardID = user.WorkNum,
                                    FEmpID = user.Id,
                                    FStatus = 1
                                });
                            }
                        }

                    }
                }
                db.Insert<AccessRecord>(accessRecord);
                return true;
            }
        }
        /// <summary>
        /// 批量添加出入记录
        /// </summary>
        /// <param name="accessRecords"></param>
        /// <returns></returns>
        public bool SaveAccessRecords(List<AccessRecord> accessRecords)
        {
            using (var db = this.NewDB())
            {
                db.BulkInsert<AccessRecord>(accessRecords);
                return true;
            }
        }
        public bool AccessRecordBatchDelete(List<Guid> ids)
        {
            using (var db = this.NewDB())
            {
                var records = db.Query<AccessRecord>().Where(c => ids.Contains(c.Id)).ToList();
                foreach (var record in records)
                {
                    if (System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + record.PicPath))
                    {
                        System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + record.PicPath);
                    }
                    db.Delete<AccessRecord>(record);
                }
                return true;
            }
        }

        public bool SaveAccessRecordRM(AccessRecord accessRecord, string machineCode)
        {
            using (var db = this.NewDB())
            {
                accessRecord.Id = Guid.NewGuid();
                accessRecord.CreateDate = DateTime.Now.ToString("yyyy-MM-dd");
                var mobile = db.Query<Mobile>().FirstOrDefault(c => c.ImeiNum == machineCode);
                if (mobile == null)
                {
                    mobile.Id = Guid.NewGuid();
                    mobile.ImeiNum = mobile.Name = machineCode;
                    db.Insert<Mobile>(mobile);
                }
                else
                {
                    accessRecord.MobileId = mobile.Id;
                }
                db.Insert<AccessRecord>(accessRecord);
                return true;
            }
        }
        /// <summary>
        /// 学校考勤
        /// </summary>
        /// <param name="query"></param>
        /// <param name="StartDate"></param>
        /// <param name="EndDate"></param>
        /// <returns></returns>
        public PageDto<XXCheckRecord> GetXXCheckRecord(QueryListModel query, DateTime StartDate, DateTime EndDate)
        {
            using (var db = this.NewDB())
            {
                var records = db.Query<AccessRecord>().ToList();
                var users = db.Query<UserInfo>().ToList();
                var holidays = db.Query<Holiday>().ToList();
                int days = (int)(EndDate - StartDate).TotalDays;
                List<DateTime> dates = new List<DateTime>();
                for (int j = 0; j < days; j++)
                {
                    DateTime date = StartDate.AddDays(j);
                    if (holidays.FirstOrDefault(c => c.StartDate <= date && c.EndDate >= date) != null)
                    {
                        continue;
                    }
                    dates.Add(date);
                }



                List<XXCheckRecord> dtos = new List<XXCheckRecord>();


                int i = 1;
                foreach(var u in users)
                {
                    var dto = GetCheckRecor(u.Id, records, dates, i);
                    dto.UserName = u.NickName;
                    dtos.Add(dto);
                    i++;
                }
                WebHelper.WriteSession("Data", dtos);
                var result = dtos.AsQueryable().Paging(query.Limit, query.Offset);
                return new PageDto<XXCheckRecord>()
                {
                    total = result.total,
                    rows = result.rows
                };
            }
        }
        XXCheckRecord GetCheckRecor(Guid userId, List<AccessRecord> records,List<DateTime> dates,int num)
        {
            XXCheckRecord dto = new XXCheckRecord();
            dto.Number = num + ""; 
            int late = 0;  //迟到
            int early = 0;  //早退
            int no = 0;  //未签
            int away = 0;  //旷工
            records = records.Where(c => c.UserId == userId).ToList();
            foreach (DateTime time in dates)
            {
                if (time.DayOfWeek == DayOfWeek.Saturday || time.DayOfWeek == DayOfWeek.Sunday)
                {
                    continue;
                }
                if (!records.Any(c => c.CreatedTime >= time.AddHours(6) && c.CreatedTime <= time.AddHours(23).AddMinutes(59)))
                {
                    away++;
                    continue;
                }
                if (!records.Any(c => c.CreatedTime >= time.AddHours(6) && c.CreatedTime <= time.AddHours(8).AddMinutes(20)))
                {
                    if (records.Any(c => c.CreatedTime >= time.AddHours(8).AddMinutes(20) && c.CreatedTime <= time.AddHours(8).AddMinutes(50)))
                    {
                        late++;
                    }
                    else
                    {
                        no++;
                    }
                }
                if (!records.Any(c => c.CreatedTime >= time.AddHours(12) && c.CreatedTime <= time.AddHours(14)))
                {
                    bool temp = false;
                    if (records.Any(c => c.CreatedTime >= time.AddHours(11).AddMinutes(30) && c.CreatedTime < time.AddHours(12)))
                    {
                        early++;
                        temp = true;
                    }

                    if (records.Any(c => c.CreatedTime > time.AddHours(14) && c.CreatedTime < time.AddHours(14).AddMinutes(30)))
                    {
                        late++;
                        temp = true;
                    }
                    if (!temp)
                    {
                        no++;
                    }

                }
                if (time.DayOfWeek != DayOfWeek.Friday)
                {
                    if (!records.Any(c => c.CreatedTime >= time.AddHours(16).AddMinutes(20) && c.CreatedTime <= time.AddHours(20)))
                    {
                        bool temp = false;
                        if (records.Any(c => c.CreatedTime >= time.AddHours(15).AddMinutes(50) && c.CreatedTime < time.AddHours(16).AddMinutes(20)))
                        {
                            early++;
                            temp = true;
                        }
                        if (records.Any(c => c.CreatedTime > time.AddHours(20) && c.CreatedTime < time.AddHours(23).AddMinutes(59)))
                        {
                            temp = true;
                        }
                        if (!temp)
                        {
                            no++;
                        }
                    }
                }
                else
                {
                    if (!records.Any(c => c.CreatedTime >= time.AddHours(15) && c.CreatedTime <= time.AddHours(20)))
                    {
                        bool temp = false;
                        if (records.Any(c => c.CreatedTime >= time.AddHours(14).AddMinutes(20) && c.CreatedTime < time.AddHours(16).AddMinutes(20)))
                        {
                            early++;
                            temp = true;
                        }
                        if (records.Any(c => c.CreatedTime > time.AddHours(20) && c.CreatedTime < time.AddHours(23).AddMinutes(59)))
                        {
                            temp = true;
                        }
                        if (!temp)
                        {
                            no++;
                        }
                    }
                }
            }
            if (early > 0)
                dto.BeEarly = early + "";
            if (late > 0)
                dto.BeLate = late + "";
            if (no > 0)
                dto.BeNo = no + "";
            if (away > 0)
                dto.BeAway = away + "";
            return dto;

        }
    }
}
